/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aptech.eproject.logictics.dao.thinh;

import aptech.eproject.logictics.db.*;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.*;
import javax.ejb.*;
import javax.persistence.*;
import org.hibernate.dialect.IngresDialect;

/**
 *
 * @author HOANGTHINH
 */
@Stateless(name = "stateless/RouteManage")
@TransactionManagement(value = TransactionManagementType.CONTAINER)
public class RouteManage implements RouteManageRemote {

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    @Resource
    private SessionContext context;
    @PersistenceContext(name = "LogicticsService")
    EntityManager em;

    /**
     * Check to see if there is any trip contain this route have status is Coming or planned
     * @param routeIds - List type
     *          list of route Id
     * @return
     *      lstRouteNotInUse: Route not in use or route in trip have status is arrived
     */
    public List isTripUseRoute(List routeIds) {
        List lstRouteNotInUse = new ArrayList();
        for (int i = 0; i < routeIds.size(); i++) {
            Integer routeId = (Integer) routeIds.get(i);
            Query query = em.createQuery("SELECT tr.route FROM TripRoute tr WHERE tr.route.routeId =?1"
                    + " AND tr.status IN(?2,?3) AND tr.isDeleted='False'");
            query.setParameter(1, routeId);
            query.setParameter(2, TripRouteStatus.Planned);
            query.setParameter(3, TripRouteStatus.Coming);
            if (query.getResultList().size() > 0) {
                continue;
            } else {
                lstRouteNotInUse.add(routeId);
            }
        }
        return lstRouteNotInUse;

    }

    /**
     * Use to remove route
     *      Find these trip id contain this route in TripRoute then change status IsDeleted of each route in trip to true
     *      Change  status isDeleted of each route in routeIds to true
     * @param routeIds - List type
     *      list of route Id
     * @return
     *      false : remove route fail
     *      true : remove route successful
     */
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public boolean removeRoute(List routeIds) {
        try {
            for (int i = 0; i < routeIds.size(); i++) {
                int routeId = Integer.parseInt(routeIds.get(i) + "");
                Query query = em.createQuery("SELECT DISTINCT tr.id.tripId FROM TripRoute tr WHERE tr.id.routeId = ?1 AND tr.isDeleted='false'");
                query.setParameter("1", routeId);
                List tripIds = query.getResultList();
                if (tripIds != null && tripIds.size() > 0) {
                    //System.out.println("Trip: ");
                    for (int j = 0; j < tripIds.size(); j++) {
                        int tripId = Integer.parseInt(tripIds.get(j) + "");
                        //System.out.print(tripId + " "+routeId);
                        TripRoutePK trPk = new TripRoutePK(routeId,tripId);
                        TripRoute tripRoute = em.find(TripRoute.class, trPk);
                        tripRoute.setIsDeleted(true);
                        em.merge(tripRoute);
                    }
                }
                //Delete Route from route table
                Route r = em.find(Route.class, routeId);
                r.setIsDeleted(true);
                em.merge(r);
            }
            return true;
        } catch (NumberFormatException nfe) {
            System.err.println("Cannot casting value ....");
            return false;
        } catch (Exception ex) {
            context.setRollbackOnly();
            System.err.println("Cannot delete entity");
            ex.printStackTrace();
            return false;
        }

    }

    /**
     * get List of branch name and branch id with condition isDeleted='False'
     * @return List
     *      List contain two object (branchId,branchName)
     */
    public List getListBranch() {
        Query query = em.createQuery("SELECT b FROM Branch b WHERE b.isDeleted='False'");
        return query.getResultList();
    }

    /**
     * add New route
     * @param fromBranchId - Integer Type
     *      existed branch Id
     * @param toBranchId - Integer Type
     *      existed branch Id
     * @param distance - Double type
     * @return
     *      true : add  route Successul
     *      false : add route Fail
     */
    public boolean addRoute(int fromBranchId, int toBranchId, double distance) {
        try {
            Branch fromBranch = em.find(Branch.class, fromBranchId);
            Branch toBranch = em.find(Branch.class, toBranchId);
            Route r = new Route(fromBranch, toBranch, distance);
            em.persist(r);
            return true;
        } catch (NullPointerException ex) {
            System.err.println("Cannot find entity....");
            return false;
        } catch (EntityExistsException eee) {
            System.err.println("Entity have already existed");
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @return List entity Route
     *      The list of route have condition isDeleted='False'
     */
    public List getListRoute() {
        Query query = em.createQuery("SELECT r FROM Route r WHERE r.isDeleted='False'");
        return query.getResultList();
    }

    /**
     * @param branchName String type
     * @return
     *      list of entity route have from branch and to branch like branch name parameter
     */
    public List getListRouteByBranchName(String branchName) {
        Query query = em.createQuery("SELECT r FROM Route r WHERE r.isDeleted='False' AND r.fromBranch.branchName like ?1 OR r.toBranch.branchName like ?2");
        query.setParameter(1, "%" + branchName + "%");
        query.setParameter(2, "%" + branchName + "%");
        return query.getResultList();
    }

    /**
     * Update route information based on routeId
     * @param routeId - integer type
     *      existed routeId
     * @param fromBranchId - integer type
     *      existed branchId
     * @param toBranchId - integer type
     *      existed branchId
     * @param distance - double type
     * @return
     *      true : update route successful
     *      false : update route fail
     */
    public boolean updateRoute(int routeId, int fromBranchId, int toBranchId, double distance) {
        try {
            Branch fromBranch = em.find(Branch.class, fromBranchId);
            Branch toBranch = em.find(Branch.class, toBranchId);
            Route r = em.find(Route.class, routeId);
            r.setFromBranch(fromBranch);
            r.setToBranch(toBranch);
            r.setDistance(distance);
            em.merge(r);
            return true;
        } catch (NullPointerException ex) {
            System.err.println("Cannot find entity....");
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public Route getRoute(int routeId)
    {
        try {
           return  em.find(Route.class, routeId);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    public String getMessage(List routeIds)
    {
        String str="";
        for (int i = 0; i < routeIds.size(); i++) {
            Integer routeId = (Integer) routeIds.get(i);
            Route r=em.find(Route.class, routeId);
            str+="\n\t from :"+r.getFromBranch().getBranchName()+" to :"+r.getToBranch().getBranchName();
        }
        return str;
    }
}
